package com.foohoo.benchmark.log;

import lombok.extern.slf4j.Slf4j;
import org.openjdk.jmh.annotations.*;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * 测试不同日志大小情况下logback同步打印性能
 * 单线程1000次, 分别打印文本: 100, 500, 1000
 * 注: 此处日志大小的计算未包含logback日志模板中打印的时间、线程名称等信息
 * Benchmark                                                  Mode  Cnt   Score    Error  Units
 * LogbackWithDiffSize.singleThreadSyncPrintSize1000Loop1000  avgt    3  22.499 ± 24.126  ms/op
 * LogbackWithDiffSize.singleThreadSyncPrintSize100Loop1000   avgt    3  11.123 ± 15.661  ms/op
 * LogbackWithDiffSize.singleThreadSyncPrintSize500Loop1000   avgt    3  14.597 ±  4.617  ms/op
 * 一句话结论: 日志越长，打印耗时越长；且打印耗时的增长幅度要陡于日志长度的增长幅度
 *
 * @author mzdbxqh
 * @date 2020-10-19 16:42
 **/
@Slf4j
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 15, time = 1)
@Measurement(iterations = 3, time = 1)
@Fork(1)
@Threads(1)
@State(Scope.Benchmark)
public class LogbackWithDiffSize {

	private static String SIZE_100;
	private static String SIZE_500;
	private static String SIZE_1000;
	private static final int LOOP_TIME = 1000;

	@Setup
	public void initLogString() {
		char targetChar = "-".charAt(0);
		char[] contentBeforeFill100 = new char[100];
		Arrays.fill(contentBeforeFill100, targetChar);
		SIZE_100 = String.copyValueOf(contentBeforeFill100);
		char[] contentBeforeFill500 = new char[500];
		Arrays.fill(contentBeforeFill500, targetChar);
		SIZE_500 = String.copyValueOf(contentBeforeFill500);
		char[] contentBeforeFill1000 = new char[1000];
		Arrays.fill(contentBeforeFill1000, targetChar);
		SIZE_1000 = String.copyValueOf(contentBeforeFill1000);
	}

	@Benchmark
	public void singleThreadSyncPrintSize100Loop1000() {
		for (int i = 0; i < LOOP_TIME; i++) {
			log.info(SIZE_100);
		}
	}

	@Benchmark
	public void singleThreadSyncPrintSize500Loop1000() {
		for (int i = 0; i < LOOP_TIME; i++) {
			log.info(SIZE_500);
		}
	}


	@Benchmark
	public void singleThreadSyncPrintSize1000Loop1000() {
		for (int i = 0; i < LOOP_TIME; i++) {
			log.info(SIZE_1000);
		}
	}
}
